package at.com.vn.chess.applet;

import javax.swing.JApplet;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.table.DefaultTableModel;

import vn.com.bip.office.smart.util.XMLHelper;
import vn.nnn.shogi.quanco.QuanCo;

import at.com.vn.chess.entity.ChessRow;
import at.com.vn.chess.entity.ChatUser;
import at.com.vn.chess.listener.ChessTableListener;
import at.com.vn.chess.listener.DialogClickListener;
import at.com.vn.chess.network.ClientUtil;
import at.com.vn.chess.util.Const;
import at.com.vn.chess.util.ChessTable;
import at.com.vn.chess.util.Msg;
import at.com.vn.chess.util.MultiColumn;

import java.awt.Color;
import java.awt.Dimension;
import java.awt.Font;
import java.awt.TextArea;
import java.awt.TextField;
import java.awt.Toolkit;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.util.ArrayList;

public class ChatApplet extends JApplet implements ActionListener, Runnable {

	private static final long serialVersionUID = -6869438049346937247L;

	private String url_servlet_base = Const.URL_CHESS_APPLICATION;
	private String url_servlet_chat = url_servlet_base + "/ChatPublicServlet";
	private String url_servlet_chat_private = url_servlet_base
			+ "/ChatPrivateServlet";

	// Variable
	private ArrayList<ChatUser> lstReturnUser;
	private ArrayList<ChessRow> lstReturnChessTable = new ArrayList<ChessRow>();

	private ClientUtil clientUtil;

	// Basic Components
	private JPanel panel = new JPanel();
	private ChessTable chessTable = new ChessTable();
	private ChessFrame chessFrame = null;
	private TextArea textResult = new TextArea();

	MultiColumn listUser;

	private JLabel lblTitle = new JLabel(Const.SHOGI_TABLE_TITLE);
	private TextField textfield = new TextField();
	private JButton button = new JButton();
	private Font ver = new Font(Const.FONT_PUBLIC_CHAT, Font.CENTER_BASELINE,
			12);

	private JComboBox feelings = new JComboBox(Const.FEELING);
	private JButton sendfeel = new JButton();

	// All Strings
	private String name = "Mr X";
	private String currentRoomID;
	private String feels;

	// Threads
	private Thread thread;

	// Thread t1 = new Thread(this);
	// Messages msg;
	// Thread t2 = new Thread(msg);
	private int tableID = 0;

	protected boolean linkClicked = false;

	public void init() {

		System.out.println("Khoi dong mot bang chat");

		// Get parameter from web
		name = this.getParameter(Const.WEB_PARAM_USER_ID);
		currentRoomID = this.getParameter(Const.WEB_PARAM_ROOM_ID);
		url_servlet_base = this.getParameter(Const.WEB_PARAM_SERVER_URL_BASE);
		url_servlet_chat = url_servlet_base + "/ChatPublicServlet";
		url_servlet_chat_private = url_servlet_base + "/ChatPrivateServlet";

		if (url_servlet_base == null || url_servlet_base.equals("")) {
			url_servlet_base = Const.URL_CHESS_APPLICATION;
			url_servlet_chat = url_servlet_base + "/ChatPublicServlet";
			url_servlet_chat_private = url_servlet_base + "/ChatPrivateServlet";
		}

		// name = JOptionPane.showInputDialog(getParent(), "Input name");

		if ((name == null) || name.equals("")) {
			name = "Mr. X";
		}

		if ((currentRoomID == null) || currentRoomID.equals("")) {
			currentRoomID = "room1";
			// System.out.println( currentRoomID );
		}

		clientUtil = new ClientUtil(getCodeBase(), url_servlet_chat, name,
				currentRoomID);

		setSize(795, 500);

		JScrollPane container = new JScrollPane(chessTable);
		getContentPane().add(container, java.awt.BorderLayout.WEST);
		chessTable.setLayout(null);

		// The first applet load, set 1 row for chess table
		lstReturnChessTable.add(new ChessRow(1, "", Const.PLAYER_NAME_BLANK,
				Const.PLAYER_NAME_BLANK, 0, 0));
		chessTable.setDataLink(lstReturnChessTable);

		chessTable.setOnClickListener(new DialogClickListener() {
			@Override
			public void createRowClicked() {
				// Check available blank chess table on this room
				if (isAvaiBlankChessTable()) {
					JOptionPane.showMessageDialog(getParent(),
							"Please use available blank chess table");
				} else {
					// Add new row
					String xmlMsg = prepareDoChessTableMsg(
							Const.PROCESS_DO_CHESS_TABLE_ADD_CHESS_TABLE,
							" has created new chess table...");
					clientUtil.sendBroadcastMessage(xmlMsg);
				}
			}

			@Override
			public void linkClicked(int rowClicked, int columnClicked) {
				// Only one click on link, when browser is not
				// IE(firefox and other)
				if (linkClicked) {
					return;
				}
				linkClicked = true;

				// get row clicked
				int id = Integer.parseInt(String.valueOf(chessTable.getModel()
						.getValueAt(rowClicked, 0)));

				ChessRow chessRowClicked = getChessRowByID(id);

				// chessRowClicked.setCurrentUserId(name);
				String title = new StringBuilder().append("Table ")
						.append(chessRowClicked.getTableId()).append(" -- ")
						.append(name).append("'s window").toString();

				// Send to server
				String xmlMsg = XMLHelper.convertListObjectToXML(
						chessRowClicked,
						Const.PROCESS_DO_CHESS_TABLE_CLICK_LINK_CHESS_TABLE,
						ChessRow.class);

				clientUtil.sendBroadcastMessage(xmlMsg);

				tableID = chessRowClicked.getTableId();

				chessFrame = new ChessFrame(title, url_servlet_chat_private,
						name, currentRoomID, tableID, ChatApplet.this);
				chessFrame.setListener(new ChessTableListener() {
					@Override
					public void closeClicked() {

						// Only one click on link, when browser is not
						// IE(firefox and other)
						linkClicked = false;

						String xmlMsg;
						// When user left, set player name for chess table
						ChessRow chessRow = getRowByPlayer(name);
						if (chessRow != null) {
							if (chessRow.getBlackOwner().equals(name)) {
								chessRow.setBlackOwner(Const.PLAYER_NAME_BLANK);
								chessRow.setBlackOwnerStatus(Const.NOT_JOINED);
							}
							if (chessRow.getWhiteOwner().equals(name)) {
								chessRow.setWhiteOwner(Const.PLAYER_NAME_BLANK);
								chessRow.setWhiteOwnerStatus(Const.NOT_JOINED);
							}

							xmlMsg = XMLHelper.convertListObjectToXML(chessRow,
									Const.PROCESS_DO_CHESS_TABLE_LEFT,
									ChessRow.class);
							clientUtil.sendBroadcastMessage(xmlMsg);
						}
					}

					@Override
					public void setPlayerClicked(String name, int playerColor,
							String status) {

						String xmlMsg;
						// When user left, set player name for chess table
						ChessRow chessRow = getActiveRow();
						if (chessRow != null) {
							if (playerColor == QuanCo.QUAN_DEN) {
								chessRow.setBlackOwner(name);
								chessRow.setBlackOwnerStatus(Const.JOINED);
							} else if (playerColor == QuanCo.QUAN_TRANG) {
								chessRow.setWhiteOwner(name);
								chessRow.setWhiteOwnerStatus(Const.JOINED);
							}

							xmlMsg = XMLHelper.convertListObjectToXML(chessRow,
									Const.PROCESS_DO_CHESS_TABLE_LEFT,
									ChessRow.class);
							clientUtil.sendBroadcastMessage(xmlMsg);
						}
					}

				});

				// open chesstable
				chessFrame.setMinimumSize(new Dimension(Const.DIALOG_WIDTH,
						Const.DIALOG_HEIGHT + 32));
				chessFrame.setPreferredSize(new Dimension(Const.DIALOG_WIDTH,
						Const.DIALOG_HEIGHT));
				chessFrame.pack();
				chessFrame.setLocationRelativeTo(null);
				chessFrame.setVisible(true);
			}
		});

		getContentPane().add(lblTitle, java.awt.BorderLayout.PAGE_START);

		getContentPane().add(panel, java.awt.BorderLayout.CENTER);
		panel.setLayout(null);
		panel.setBackground(new Color(242, 167, 0));

		panel.add(textResult);
		textResult.setBounds(3, 20, 280, 350);
		textResult.setFont(ver);
		textResult.setEditable(false);
		textResult.setText("Chat Applet By BipSystem VN\n");
		textResult.append("------------------------------------------\n");

		JLabel listTitle = new JLabel(
				"UserId       Win        Lost         Rank        Gold");
		panel.add(listTitle);
		listTitle.setBounds(285, 6, 250, 15);

		listUser = new MultiColumn(null, 5);

		panel.add(listUser);
		listUser.setBounds(286, 20, 270, 350);
		listUser.setFont(ver);
		listUser.setLayout(null);
		listUser.setSize(240, 350);

		panel.add(textfield);
		textfield.setBounds(3, 380, 280, 25);
		textfield.setFont(ver);
		textfield.setText("Type The Text Here");
		textfield.addKeyListener(new KeyAdapter() {
			public void keyPressed(KeyEvent e) {
				int key = e.getKeyCode();
				if (key == KeyEvent.VK_ENTER) {
					Toolkit.getDefaultToolkit().beep();

					String xmlMsg = prepareChatMsg(
							Const.PROCESS_CHAT_PUBLIC_CHAT, textfield.getText());
					clientUtil.sendBroadcastMessage(xmlMsg);

					textfield.setText("");
				}
			}
		});

		panel.add(button);
		button.setBounds(3, 415, 280, 25);
		button.setText(name + " Says");
		button.setFont(ver);
		button.addActionListener(this);

		panel.add(feelings);
		feelings.setBounds(3, 450, 120, 25);
		feelings.setFont(ver);
		panel.add(sendfeel);

		sendfeel.setBounds(135, 450, 150, 25);
		sendfeel.setFont(ver);
		sendfeel.setText(Const.BUTTON_SEND_FEELING);
		sendfeel.addActionListener(this);

		String xmlMsg = prepareChatMsg(Const.PROCESS_CHAT_PUBLIC_JOIN,
				" has joined...");
		showResult(clientUtil.doPrivateData(xmlMsg));

		xmlMsg = prepareDoChessTableMsg(
				Const.PROCESS_DO_CHESS_TABLE_GET_CHESS_TABLE, " has joined...");
		showResult(clientUtil.doPrivateData(xmlMsg));

		xmlMsg = prepareChatMsg(Const.PROCESS_CHAT_PUBLIC_JOIN,
				" has joined...");
		clientUtil.sendBroadcastMessage(xmlMsg);

	}

	private boolean isAvaiBlankChessTable() {
		// check available blank chess table on this room
		for (int i = 0; i < chessTable.getModel().getRowCount(); i++) {
			if (chessTable.getModel().getValueAt(i, 3)
					.equals(Const.STATUS_IDLE)) {
				return true;
			}
		}
		return false;
	}

	@Override
	public void start() {
		thread = new Thread(this);
		thread.start();
	}

	@Override
	public void destroy() {

		// Send to server
		String xmlMsg;
		// When user left, set player name for chess table
		ChessRow chessRow = getRowByPlayer(name);
		if (chessRow != null) {
			if (chessRow.getBlackOwner().equals(name)) {
				chessRow.setBlackOwner(Const.PLAYER_NAME_BLANK);
				chessRow.setBlackOwnerStatus(1);
			}
			if (chessRow.getWhiteOwner().equals(name)) {
				chessRow.setWhiteOwner(Const.PLAYER_NAME_BLANK);
				chessRow.setWhiteOwnerStatus(1);
			}

			xmlMsg = XMLHelper.convertListObjectToXML(chessRow,
					Const.PROCESS_DO_CHESS_TABLE_LEFT, ChessRow.class);
			clientUtil.sendBroadcastMessage(xmlMsg);
		}

		// When user left, remove out of list, show all client
		xmlMsg = prepareChatMsg(Const.PROCESS_CHAT_PUBLIC_LEFT, " has left...");
		clientUtil.sendBroadcastMessage(xmlMsg);
	}

	@Override
	public void actionPerformed(ActionEvent e) {
		if (e.getSource() == button) {
			// sent to server
			String xmlMsg = prepareChatMsg(Const.PROCESS_CHAT_PUBLIC_CHAT,
					textfield.getText());
			clientUtil.sendBroadcastMessage(xmlMsg);
			textfield.setText("");
		}

		if (e.getSource() == sendfeel) {
			if (feelings.getSelectedItem().equals("I Feel ...")) {
				return;
			}

			feels = String.valueOf(feelings.getSelectedItem());
			String xmlMsg = prepareChatMsg(Const.PROCESS_CHAT_PUBLIC_CHAT,
					" feels " + feels);
			clientUtil.sendBroadcastMessage(xmlMsg);
		}

	}

	@Override
	public void run() {
		Thread thisThread = Thread.currentThread();
		while (thread == thisThread) {
			try {
				Thread.sleep(Const.ONE_SECOND);
			} catch (InterruptedException e) {
			}
			String xmlMsg = clientUtil.receiverMessage();
			showResult(xmlMsg);
		}

	}

	private ChessRow getChessRowByID(int tableID) {
		for (ChessRow irow : lstReturnChessTable) {
			if (irow.getTableId() == tableID) {
				return irow;
			}
		}
		return null;
	}

	private ChessRow getRowByPlayer(String userID) {
		for (ChessRow irow : lstReturnChessTable) {
			if (irow.getBlackOwner().equals(userID)
					|| irow.getWhiteOwner().equals(userID)) {
				return irow;
			}
		}
		return null;
	}

	private ChessRow getActiveRow() {
		for (ChessRow irow : lstReturnChessTable) {
			if (irow.getTableId() == tableID) {
				return irow;
			}
		}
		return null;
	}

	private String prepareChatMsg(String propName, String message) {
		ChatUser user = new ChatUser();
		user.setUserID(name);
		user.setRoomID(currentRoomID);
		user.setChatMsg(message);
		user.setIsActive(1);
		return XMLHelper.convertListObjectToXML(user, propName, ChatUser.class);
	}

	private String prepareDoChessTableMsg(String propName, String message) {
		ChessRow chessRow = new ChessRow();
		chessRow.setCurrentRoomId(currentRoomID);
		chessRow.setBlackOwner(Const.PLAYER_NAME_BLANK);
		chessRow.setBlackOwnerStatus(Const.NOT_JOINED);
		chessRow.setWhiteOwner(Const.PLAYER_NAME_BLANK);
		chessRow.setWhiteOwnerStatus(Const.NOT_JOINED);

		return XMLHelper.convertListObjectToXML(chessRow, propName,
				ChessRow.class);
	}

	@SuppressWarnings("unchecked")
	private void showChatPublic(String resultXML) {

		String processName = XMLHelper.getProcessName(resultXML);
		lstReturnUser = (ArrayList<ChatUser>) XMLHelper.convertXMLToListObject(
				resultXML, ChatUser.class);
		String publicRoomID = getPublicRoomID();
		if (publicRoomID.equals(currentRoomID)) {
			// Refresh listUser if not chat
			if (!processName.contains(Const.PROCESS_CHAT_PUBLIC_CHAT)) {
				listUser.removeAllItem();
				for (ChatUser user : lstReturnUser) {
					if (user.getIsDeleted() != Const.TRUE
							&& user.getRoomID().equals(currentRoomID)) {
						listUser.add(user.getUserID(),
								String.valueOf(user.getWin()),
								String.valueOf(user.getLoss()),
								String.valueOf(user.getRank_id()),
								String.valueOf(user.getGold()));
					}
				}
				refreshPanel(listUser.getColumnData());
			}

			for (ChatUser user : lstReturnUser) {
				if (user.getIsActive().equals(Const.TRUE)
						&& user.getRoomID().equals(currentRoomID)) {
					if (!processName.contains(Const.PROCESS_CHAT_PUBLIC_CHAT)) {
						textResult.append(user.getUserID() + " "
								+ user.getChatMsg() + "\n");
					} else {
						textResult.append(user.getUserID() + " : "
								+ user.getChatMsg() + "\n");
					}
				}
			}
		}
	}

	private void refreshPanel(String[][] columnData) {

		panel.remove(listUser);
		panel.revalidate();

		listUser = new MultiColumn(columnData, 5);
		panel.add(listUser);
		listUser.setBounds(286, 20, 270, 350);
		listUser.setFont(ver);
		listUser.setLayout(null);
		listUser.setSize(240, 350);
		listUser.refreshList();

		panel.revalidate();
	}

	@SuppressWarnings("unchecked")
	private void showDoChessTable(String resultXML) {
		lstReturnChessTable = (ArrayList<ChessRow>) XMLHelper
				.convertXMLToListObject(resultXML, ChessRow.class);

		// Clean all data if available
		DefaultTableModel modal = chessTable.getModel();
		modal.setNumRows(0);

		for (ChessRow iData : lstReturnChessTable) {
			if (currentRoomID.trim().equals(iData.getCurrentRoomId().trim())) {
				String status = iData.getRowStatus();

				Object rowData[] = new Object[] {
						String.valueOf(iData.getTableId()),
						iData.getBlackOwner(), iData.getWhiteOwner(), status };
				chessTable.getModel().addRow(rowData);
			}
		}

		if (chessTable.getModel().getRowCount() == 0) {
			return;
		} else {
			chessTable.RefreshTable(name, lstReturnChessTable);
		}
	}

	@SuppressWarnings("unchecked")
	private void showResult(String resultXML) {

		String processName = XMLHelper.getProcessName(resultXML);

		if (processName.contains(Const.SERVICE_DO_CHESS_TABLE)) {
			showDoChessTable(resultXML);
		} else if (processName.contains(Const.SERVICE_CHAT_PUBLIC)) {
			showChatPublic(resultXML);
		} else if (processName.contains(Const.SERVICE_POPULAR_RELOGIN)) {
			// Show popular message
			lstReturnUser = (ArrayList<ChatUser>) XMLHelper
					.convertXMLToListObject(resultXML, ChatUser.class);
			if (lstReturnUser.get(0).getUserID().equals(name)) {
				JOptionPane.showMessageDialog(getComponent(0),
						Msg.MSG_ALREADY_LOGINED);
			}

		}
	}

	private String getPublicRoomID() {
		// Display msg
		for (ChatUser user : lstReturnUser) {
			if (user.getIsActive().equals(1)) {
				return user.getRoomID();
			}
		}
		return "";

	}
}